/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author xxxcsg
 */

#include "PowerBindGather.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../3rd/cJSON.h"

#include "log.h"
#include "Utility.h"
#include "parameter.h"

int gather_login_info_json(char **info_json)
{
    int ret = 0;
    cJSON *root_info = NULL;
    cJSON *osname_response = NULL;
    cJSON *arch_response = NULL;
    cJSON *chiptype_response = NULL;

    root_info = cJSON_CreateObject();
    if (root_info == NULL)  
    {  
        debug_msg("Error root_info: [%s]\n", cJSON_GetErrorPtr());
        ret = -1;
        goto end;
    }
    
    const char* osName = GetOSFullName();
    const char* chiptype = GetChipType();
    FILE *fp;
    char buffer[1024];
    fp = popen("getconf LONG_BIT", "r");
    if(fp == NULL)
    {
        const char *error = "cmd error";
        strcpy(buffer, error);
        printf("buffer:%s\n", buffer);
    }
    else
    {
	if(fgets(buffer, sizeof(buffer), fp) == NULL)
        {
            const char *error = "cmd error";
            strcpy(buffer, error);
            printf("buffer:%s\n", buffer);
        }
	printf("buffer:%s\n", buffer);
	pclose(fp);
    }
    cJSON_AddStringToObject(root_info,"code","000");
    
    arch_response = cJSON_CreateString(buffer);
    cJSON_AddItemToObject(root_info,"arch",arch_response);
    
    osname_response = cJSON_CreateString(osName);
    cJSON_AddItemToObject(root_info,"osname",osname_response);
    
    chiptype_response = cJSON_CreateString(chiptype);
    cJSON_AddItemToObject(root_info,"chiptype",chiptype_response);

    *info_json = cJSON_Print(root_info);
end:
    if (root_info != NULL) { cJSON_Delete(root_info); }
    return ret;
}

int gather_component_info_tools_json(const char *json_cmd, char **json_reponse)
{
    int ret = 0;
    cJSON *root_conf = NULL;
    cJSON *item_conf = NULL;
    cJSON *item_index = NULL;

    cJSON *root_info = NULL;
    cJSON *item_response = NULL;

    root_conf = cJSON_Parse(json_cmd);
    if (root_conf == NULL) 
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "error_info:%s\n", error_ptr);
        }
        ret = -1;
        goto end;
    }

    root_info = cJSON_CreateObject();
    if (root_info == NULL)  
    {  
        debug_msg("Error root_info: [%s]\n", cJSON_GetErrorPtr());
        ret = -1;
        goto end;
    }

    item_conf = cJSON_GetObjectItem(root_conf, "cmd");
    item_index = cJSON_GetObjectItem(root_conf, "cmdindex");

    FILE *fp;
	char buffer[1024];

	fp = popen(item_conf->valuestring, "r");
    if(fp == NULL)
    {
        const char *error = "cmd error";
        strcpy(buffer, error);
        printf("buffer:%s\n", buffer);
    }
    else
    {
	    if(fgets(buffer, sizeof(buffer), fp) == NULL)
        {
            const char *error = "cmd error";
            strcpy(buffer, error);
            printf("buffer:%s\n", buffer);
        }
	    printf("buffer:%s\n", buffer);
	    pclose(fp);
    }

    item_response = cJSON_CreateString(buffer);
    cJSON_AddItemToObject(root_info,"response",item_response);
    cJSON_AddItemReferenceToObject(root_info,"cmd",item_conf);
    cJSON_AddItemReferenceToObject(root_info,"cmdindex",item_index);

    *json_reponse = cJSON_Print(root_info);
end:
    if (root_conf != NULL) { cJSON_Delete(root_conf); }
    if (root_info != NULL) { cJSON_Delete(root_info); }
    return ret;
}

int gather_component_singlefile_info_json(const char *json_path, char **info_json)
{
    int ret = 0;
    cJSON *root_conf = NULL;
    cJSON *item_conf = NULL;
    cJSON *item_index = NULL;

    cJSON *root_info = NULL;
    cJSON  *item_hash = NULL;

    root_conf = cJSON_Parse(json_path);
    if (root_conf == NULL) 
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "error_info:%s\n", error_ptr);
        }
        ret = -1;
        goto end;
    }

    char digest_hex[DIGEST_MAX_LEN * 2 + 1] = { 0 };
    root_info = cJSON_CreateObject();
    if (root_info == NULL)  
    {  
        debug_msg("Error root_info: [%s]\n", cJSON_GetErrorPtr());
        ret = -1;
        goto end;
    }

    item_conf = cJSON_GetObjectItem(root_conf, "filepath");
    item_index = cJSON_GetObjectItem(root_conf, "fileindex");
    if(hash_file(item_conf->valuestring, digest_hex) == 0)
    {

        item_hash = cJSON_CreateString(digest_hex);
    }
    else
    {
        item_hash = cJSON_CreateString("");
    }
    cJSON_AddItemToObject(root_info,"filehash",item_hash);
    cJSON_AddItemReferenceToObject(root_info,"filepath",item_conf);
    cJSON_AddItemReferenceToObject(root_info,"fileindex",item_index);
    *info_json = cJSON_Print(root_info);
end:
    if (root_conf != NULL) { cJSON_Delete(root_conf); }
    if (root_info != NULL) { cJSON_Delete(root_info); }
    return ret;
}

int gather_component_info_json(const char *conf_path, char **info_json)
{
    int ret = 0;
    char *conf_data = NULL;
    cJSON *root_conf = NULL;
    cJSON *root_info = NULL;

    ret = read_file(conf_path, &conf_data);
    if (ret != 0)
    {
        printf("read_file failed: %s\n", conf_path);
        ret = -1;
        goto end;
    }

    root_conf = cJSON_Parse(conf_data);
    if (root_conf == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "error_info:%s\n", error_ptr);
        }
        ret = -1;
        goto end;
    }

    free(conf_data);
    conf_data = NULL;

    cJSON *item_conf = NULL, *array_item_conf = NULL, *array_item_checkpath = NULL, *array_item_path = NULL, *item_path = NULL;
    cJSON *item_comp = NULL;
    int num_of_comp = 0;
    int num_of_path = 0;

    cJSON *array_item_info = NULL, *array_item_hash = NULL, *item_hash = NULL;
    cJSON *item_comp_info = NULL;

    char digest_hex[DIGEST_MAX_LEN * 2 + 1] = { 0 };

    root_info = cJSON_CreateObject();
    if (root_info == NULL)  
    {  
        debug_msg("Error root_info: [%s]\n", cJSON_GetErrorPtr());
        ret = -1;
        goto end;
    }

    item_conf = cJSON_GetObjectItem(root_conf, "OSVersion");
    cJSON_AddItemReferenceToObject(root_info, "OSVersion", item_conf);

    item_conf = cJSON_GetObjectItem(root_conf, "ReleaseTime");
    cJSON_AddItemReferenceToObject(root_info, "ReleaseTime", item_conf);

    array_item_conf = cJSON_GetObjectItem(root_conf, "ComponentLinks");
    num_of_comp = cJSON_GetArraySize(array_item_conf);
    array_item_info = cJSON_CreateArray();

    for (int i = 0; i < num_of_comp; ++i)
    {
        item_comp = cJSON_GetArrayItem(array_item_conf, i);
        if (item_comp == NULL)
        {
            continue;
        }

        item_comp_info = cJSON_CreateObject();

        item_conf = cJSON_GetObjectItem(item_comp, "Name");
        cJSON_AddItemReferenceToObject(item_comp_info, "Name", item_conf);

        item_conf = cJSON_GetObjectItem(item_comp, "Version");
        cJSON_AddItemReferenceToObject(item_comp_info, "Version", item_conf);

        array_item_checkpath = cJSON_GetObjectItem(item_comp, "CheckPath");
        cJSON_AddItemReferenceToObject(item_comp_info, "CheckPath", array_item_checkpath);

        array_item_path = cJSON_GetObjectItem(item_comp, "Path");
        num_of_path = cJSON_GetArraySize(array_item_path);

        array_item_hash = cJSON_CreateArray();
        for (int j = 0; j < num_of_path; ++j)
        {
            item_path = cJSON_GetArrayItem(array_item_path, j);
            hash_file(item_path->valuestring, digest_hex);
            item_hash = cJSON_CreateString(digest_hex);
            cJSON_AddItemToArray(array_item_hash, item_hash); 
        }
        cJSON_AddItemToObject(item_comp_info, "Hash", array_item_hash);

        cJSON_AddItemToArray(array_item_info, item_comp_info); 
    }

    cJSON_AddItemToObject(root_info, "ComponentLinks", array_item_info);

    *info_json = cJSON_Print(root_info);
end:
    if (conf_data != NULL) { free(conf_data); }
    if (root_conf != NULL) { cJSON_Delete(root_conf); }
    if (root_info != NULL) { cJSON_Delete(root_info); }
    return ret;
}

int gather_component_info_jsonEx(const char *conf_json, char **info_json)
{
    int ret = 0;
    cJSON *root_conf = NULL;
    cJSON *root_info = NULL;
    root_conf = cJSON_Parse(conf_json);
    if (root_conf == NULL) {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL) {
            fprintf(stderr, "error_info:%s\n", error_ptr);
        }
        ret = -1;
        goto end;
    }

    cJSON *item_conf = NULL, *array_item_conf = NULL, *array_item_path = NULL, *item_path = NULL;
    cJSON *item_comp = NULL;
    int num_of_comp = 0;
    int num_of_path = 0;

    cJSON *array_item_info = NULL, *array_item_hash = NULL, *item_hash = NULL;
    cJSON *item_comp_info = NULL;

    char digest_hex[DIGEST_MAX_LEN * 2 + 1] = { 0 };

    root_info = cJSON_CreateObject();
    if (root_info == NULL)  
    {  
        debug_msg("Error root_info: [%s]\n", cJSON_GetErrorPtr());
        ret = -1;
        goto end;
    }

    item_conf = cJSON_GetObjectItem(root_conf, "OSVersion");
    cJSON_AddItemReferenceToObject(root_info, "OSVersion", item_conf);

    item_conf = cJSON_GetObjectItem(root_conf, "ReleaseTime");
    cJSON_AddItemReferenceToObject(root_info, "ReleaseTime", item_conf);

    array_item_conf = cJSON_GetObjectItem(root_conf, "ComponentLinks");
    num_of_comp = cJSON_GetArraySize(array_item_conf);
    array_item_info = cJSON_CreateArray();

    for (int i = 0; i < num_of_comp; ++i)
    {
        item_comp = cJSON_GetArrayItem(array_item_conf, i);
        if (item_comp == NULL)
        {
            continue;
        }

        item_comp_info = cJSON_CreateObject();

        item_conf = cJSON_GetObjectItem(item_comp, "Name");
        cJSON_AddItemReferenceToObject(item_comp_info, "Name", item_conf);

        item_conf = cJSON_GetObjectItem(item_comp, "Version");
        cJSON_AddItemReferenceToObject(item_comp_info, "Version", item_conf);

        array_item_path = cJSON_GetObjectItem(item_comp, "Path");
        num_of_path = cJSON_GetArraySize(array_item_path);

        array_item_hash = cJSON_CreateArray();
        for (int j = 0; j < num_of_path; ++j)
        {
            item_path = cJSON_GetArrayItem(array_item_path, j);
            if(hash_file(item_path->valuestring, digest_hex) == 0)
            {
                item_hash = cJSON_CreateString(digest_hex);
            }
            else
            {
                item_hash = cJSON_CreateString("");
            }
            cJSON_AddItemToArray(array_item_hash, item_hash); 
        }
        cJSON_AddItemToObject(item_comp_info, "Hash", array_item_hash);

        cJSON_AddItemToArray(array_item_info, item_comp_info); 
    }

    cJSON_AddItemToObject(root_info, "ComponentLinks", array_item_info);

    *info_json = cJSON_Print(root_info);
end:
    if (root_conf != NULL) { cJSON_Delete(root_conf); }
    if (root_info != NULL) { cJSON_Delete(root_info); }
    return ret;
}
